﻿
#include <iostream>
#include <thread>
#include <windows.h>


void createMinidump();
void createFullDump();
LONG WINAPI DumpException(EXCEPTION_POINTERS* info);

constexpr int64_t BTN_ID_MINIDUMP = 1000;
constexpr int64_t BTN_ID_FULL_DUMP = 1001;
constexpr int64_t BTN_ID_CRASH_DUMP = 1002;
constexpr int64_t BTN_ID_ASYNC_DUMP = 1003;

// 定义窗口类名和窗口标题
#define WINDOW_CLASS_NAME L"SampleWindow"

// 定义窗口过程函数，用于处理窗口消息
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_COMMAND:
    {
        auto btnID =  LOWORD(wParam);
        std::cout <<"WM_COMMAND, Button Click, button ID:" << btnID << std::endl;
        if (btnID == BTN_ID_MINIDUMP)
        {
            createMinidump();
        }
        else if(btnID == BTN_ID_FULL_DUMP)
        {
            createFullDump();
        }
        else if(btnID == BTN_ID_CRASH_DUMP)
        {
            int *p = nullptr;
            *p = 9;
        }
        else if(btnID == BTN_ID_ASYNC_DUMP)
        {
            std::thread t([](){
                std::cout << "Crash Thread Started!!" << std::endl;
                int *p = nullptr;
                *p = 9;
            });
            t.join();
        }
    }
    case WM_CREATE:
    {
        return 0;
    }
    case WM_DESTROY: // 当窗口被销毁时，发送退出消息
        PostQuitMessage(0);
        return 0;
    case WM_PAINT: // 当窗口需要绘制时，使用默认的绘制函数
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // All painting occurs here, between BeginPaint and EndPaint.
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_GRAYTEXT +1));
        EndPaint(hwnd, &ps);
    }
        return 0;
    default: // 对于其他消息，使用默认的窗口过程函数
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

// 定义主函数，用于创建和显示窗口
int WINAPI main()
{
    std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;

    LPTOP_LEVEL_EXCEPTION_FILTER oldExceptionFilter = nullptr;
    oldExceptionFilter = SetUnhandledExceptionFilter(&DumpException);

    HINSTANCE hInstance = GetModuleHandleW(nullptr);
    // 注册窗口类
    WNDCLASS wc = { 0 };
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = WindowProc; // 指定窗口过程函数
    wc.hInstance = hInstance; // 指定应用程序实例句柄
    wc.lpszClassName = WINDOW_CLASS_NAME; // 指定窗口类名
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    RegisterClass(&wc);

    // 创建窗口
    HWND hwnd = CreateWindow(
        WINDOW_CLASS_NAME, // 窗口类名
        L"Create Dump File", // 窗口标题
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, // 窗口样式，包括可调整大小和可见
        CW_USEDEFAULT, // 窗口水平位置，由系统自动选择
        CW_USEDEFAULT, // 窗口垂直位置，由系统自动选择
        600, // 窗口宽度，由系统根据窗口类和样式自动计算
        400, // 窗口高度，由系统根据窗口类和样式自动计算
        nullptr, // 父窗口句柄，没有则为NULL
        nullptr, // 窗口菜单句柄，没有则为NULL
        hInstance, // 应用程序实例句柄
        nullptr // 附加参数，没有则为NULL
    );

    // 检查窗口是否创建成功
    if (hwnd == nullptr)
    {
        MessageBox(nullptr, L"创建窗口失败！", L"错误", MB_OK | MB_ICONERROR);
        return -1;
    }

    CreateWindowEx(0,
                   L"Button",
                   L"Minidump",
                   WS_CHILD | WS_BORDER | WS_VISIBLE,
                   10, 20, 100, 40,
                   hwnd,
                   (HMENU)BTN_ID_MINIDUMP,
                   hInstance,
                   nullptr);

    CreateWindowEx(0,
                   L"Button",
                   L"Full Dump",
                   WS_CHILD | WS_BORDER | WS_VISIBLE,
                   210, 20, 100, 40,
                   hwnd,
                   (HMENU)BTN_ID_FULL_DUMP,
                   hInstance,
                   nullptr);

    CreateWindowEx(0,
                   L"Button",
                   L"Crash Dump",
                   WS_CHILD | WS_BORDER | WS_VISIBLE,
                   10, 120, 100, 40,
                   hwnd,
                   (HMENU)BTN_ID_CRASH_DUMP,
                   hInstance,
                   nullptr);


    CreateWindowEx(0,
                   L"Button",
                   L"Thread Crash Dump",
                   WS_CHILD | WS_BORDER | WS_VISIBLE,
                   190, 120, 150, 40,
                   hwnd,
                   (HMENU)BTN_ID_ASYNC_DUMP,
                   hInstance,
                   nullptr);

    // 进入消息循环，等待用户操作
    MSG msg { };
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg); // 转换虚拟键消息为字符消息
        DispatchMessage(&msg); // 分发消息给相应的窗口过程函数
    }

    SetUnhandledExceptionFilter(oldExceptionFilter);

    return (int)msg.wParam;
}